//========================================================//
// Cryptography interfaces				                      //
// Authors: Kozlov Dmitry aka LandFox kozlov@ccfit.nsu.ru //
//          Bezdolnyj Alexey aka BAM  bamalex@ngs.ru      //
//          Krechetov Anton aka kae kae@gorodok.net       //
// NSU FIT August - October 2004                          //
//========================================================//

#ifndef _BAM_CRYPTO_INTERFACE_
#define _BAM_CRYPTO_INTERFACE_

//#include "C:\\Documents and Settings\\sfaktorovich\\My Documents\\remoteconsole2\\vld.h"
#include "../common/packet.h"
#include "md5.h"
#include "des.h"
#include <time.h>
#include <stdlib.h>
#include "cryptint.h"
#include "../common/exception.h"

namespace BAM {

  class iCryptoTransform
	{
	  public:
	    virtual ~iCryptoTransform(){}
	    virtual void setKey(const cPacket &P) = 0;
	    virtual dword getKeyLength() = 0;
	    virtual cPacket transform(const cPacket &P) = 0;
	};

	class CryptoException : public cException
	{
		public:
			CryptoException(const char * mesg)
				: cException(mesg) {};
	};

	static const CryptoException EXC_WrongKeySize("Wrong key size or init value.");
	static const CryptoException EXC_NoKey("Not set key.");
	static const CryptoException EXC_WrongDataSize("Wrong data size.");
	static const CryptoException EXC_WrongDecrypt("Wrong password name.");

	static const CryptoException EXC_NoLogin("No such login name");

	class cMD5Transform : public iCryptoTransform
	{
		public:
			cMD5Transform() {}
			void setKey(const cPacket &P);
			dword getKeyLength();
			cPacket transform(const cPacket &P);
	};
	
	class cHMAC_MD5Transform : public iCryptoTransform
  {
    cPacket vHMacKey;

    public:
      cHMAC_MD5Transform();
      ~cHMAC_MD5Transform();
      void setKey(const cPacket &P) {
				setKey(P, true);
      }
      void setKey(const cPacket &P, bool nmd5);
      dword getKeyLength();
      cPacket transform(const cPacket &P);

			static const dword DEFAULT_KEYLENGTH = 16;
  };

  class c3DES_ENCTransform : public iCryptoTransform
	{
		des3_context v3DES_CTX;
		byte vIVPacket[8];

		public:

		~c3DES_ENCTransform() {}
		c3DES_ENCTransform() {}
		void setKey(const cPacket &P);
		void setKey(const cPacket &Key, const cPacket &IV);
		dword getKeyLength();
		cPacket transform(const cPacket &P);

		static const dword DEFAULT_KEYLENGTH = 16;
	};

  class c3DES_DECTransform : public iCryptoTransform
  {
    des3_context v3DES_CTX;
		byte vIVPacket[8];

    public:

   	~c3DES_DECTransform() {}
    c3DES_DECTransform() {}
    void setKey(const cPacket &P);
    void setKey(const cPacket &Key, const cPacket &IV);
    dword getKeyLength();
    cPacket transform(const cPacket &P);

		static const dword DEFAULT_KEYLENGTH = 16;
  };
	
	class cRandGenerator {
		public:
			cRandGenerator()
			{
				srand((unsigned int)~time(NULL));
			}
			cPacket GeneratePacket(dword length);
			void GenerateBlock(byte * block, dword length);//deprecated
	};

	cRandGenerator& rndGen();

	class cLoginManager
	{
	protected:
		virtual cPacket getPassword(const cPacket &login);

	public:
		//cLoginManager();
		void initTransform(iCryptoTransform *Trans, const cPacket &P, bool hash = false);//<-hash added by kae
		virtual cLoginManager* clone() const;
	};

	const byte SECURE_DH_1024[] = "DA9A18547FF03B385CC16508C173A7EF4EB61CB40EF8FEF3B31F145051676166BCDC3FE6B799FC394D08C26385F9413F896E09117E46209D6923602683CEA100924A6EE695281775C619DAA94EA8CB3691B4275B0183F1D39639EBC92995FE645D6C1BC28D409E585549BBD2C5DCDD6C208B04EADD8B7A6D997F72CBAD88390F";

	static const dword DHKEYLen = 128;

	class cDHManager {
		cPacket vPub;
		cPacket vPriv;
		cCryptIntManager * vManager;

		void reverse(unsigned char * data) const;
	
		public:

		cDHManager();
		~cDHManager();
		cPacket getPublic() const;
		cPacket agree(const cPacket& pub) const;
	};

} //End namespace BAM

#endif // _BAM_CRYPTO_INTERFACE_
